package com.sc.nft.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.dao.*;
import com.sc.nft.dto.MetaMapSettleDTO;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.SaasTaskBurialPointDTO;
import com.sc.nft.entity.vo.EquityPoPonsolidatedPaymentDetailsVO;
import com.sc.nft.entity.vo.SecondEquityPropTradingTendPageVO;
import com.sc.nft.entity.vo.secondEquityProp.*;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.exception.ModelException;
import com.sc.nft.helper.MessageQueueHelper;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.util.OrderNoUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 二级-权益道具订单表服务接口实现
 *
 * @author Sun
 * @description 由 Mybatisplus Code Generator 创建
 * @since 2024-04-07 14:18:41
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SecondEquityPropsOrderServiceImpl implements SecondEquityPropsOrderService {

    private final EquityPropsDao equityPropsDao;
    private final EquitySharePanelDao equitySharePanelDao;
    private final SecondEquityPropsConfigDao equityPropsConfigDao;
    private final UserEquityPropsService userEquityPropsService;
    private final UserEquityPropsDao userEquityPropsDao;
    private final SecondEquityPropsDao secondEquityPropsDao;
    private final SecondEquityPropsConfigDao configDao;
    private final SecondEquityPropsOrderDao equityPropsOrderDao;
    private final UserWalletService userWalletService;
    private final RedissonClient redisson;
    private final StaticDataDao staticDataDao;
    private final ScrollWantSellDao wantSellDao;
    private final EquitySharePoolService equitySharePoolService;
    private final SecondEquityPropsOrderDao secondEquityPropsOrderDao;
    private final SecondEquityPropsConfigDao secondEquityPropsConfigDao;
    private final UserInfoDao userInfoDao;
    private final MessageQueueHelper messageQueueHelper;
    private final RedisTemplate redisTemplate;
    private final ScrollShopDao scrollShopDao;
    private final ScrollConfigDao scrollConfigDao;
    private final ScOrderSettleService orderSettleService;
    private final PayOrderDao payOrderDao;
    private final PayOrderItemDao payOrderItemDao;
    private final ScrollWantBuyDao scrollWantBuyDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SecondEquityPropCreateOrderVO createOrder(UserInfo userInfo, Long equityPropsId, List<Long> productIds) {
        EquityProps equityProps = equityPropsDao.getById(equityPropsId);
        Assert.notNull(equityProps, () -> new GlobalRunTimeException("未找到该商品"));
        SecondEquityPropsConfig config = configDao.getLastOneByEquityPropsId(equityPropsId);
        Assert.notNull(config, () -> new GlobalRunTimeException("该道具已下架"));
        Assert.isFalse(equityPropsOrderDao.hasWaitPayOrder(userInfo.getId()), () -> new GlobalRunTimeException(ErrorCode.WAIT_PAY_ORDER));
        List<Long> filterList = Lists.newArrayList();
        DateTime now = DateTime.now();
        BigDecimal sumPayAmount = BigDecimal.ZERO;
        List<Long> orderIds = Lists.newArrayList();

        for (Long productId : productIds) {
            SecondEquityProps secondEquityProps = secondEquityPropsDao.getById(productId);
            if (ObjectUtil.isNull(secondEquityProps) || secondEquityProps.getStatus() != ConSignStatus.ON_SALES) {
                filterList.add(productId);
                continue;
            }
            Assert.isTrue(secondEquityProps.getUserId().longValue() != userInfo.getId().longValue(), () -> new GlobalRunTimeException("不能购买自己寄售的道具"));
            SecondEquityPropsOrder order = new SecondEquityPropsOrder();
            order.setSecondEquityPropsId(secondEquityProps.getId());
            order.setEquityPropsId(equityPropsId);
            order.setUserEquityPropsId(secondEquityProps.getUserEquityPropsId());
            order.setSalesUserId(secondEquityProps.getUserId());
            order.setBuyUserId(userInfo.getId());
            order.setBuyPrice(secondEquityProps.getSalesPrice());
            order.setCharge(secondEquityProps.getCharge());
            order.setStatus(OrderStatusEnum.WAIT_PAY);
            order.setOrderNo(OrderNoUtil.getOrderNo(String.valueOf(PayTypeEnum.SECOND_EQUITY_PROPS.getCode())));
            order.setDealTime(now);
            order.setCloseTime(DateUtil.offsetMinute(now, 3));
            order.setRealAmount(order.getBuyPrice().subtract(order.getCharge()));
            order.setFirstTitle(equityProps.getFirstTitle());
            order.setBuySumCount(1);
            order.setIsSettlePay(false);
            order.insert();
            Assert.isTrue(secondEquityPropsDao.updateConsignStatusToLock(secondEquityProps.getId()), () -> new GlobalRunTimeException("该商品已被他人锁定"));
            sumPayAmount = sumPayAmount.add(order.getBuyPrice());
            orderIds.add(order.getId());
        }
        if (CollUtil.isNotEmpty(filterList)) {
            throw new ModelException(filterList, ErrorCode.GOODS_ORDER_LOCK);
        }
        SecondEquityPropCreateOrderVO vo = new SecondEquityPropCreateOrderVO();
        vo.setRealAmount(sumPayAmount.toPlainString());
        vo.setEquityPropsId(equityPropsId);
        vo.setOrderIds(orderIds);
        vo.setExpirationTimeStamp(DateUtil.offsetMinute(now, 3).getTime());
        vo.setNowTimeStamp(now.getTime());
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paySuccess(PayOrder payOrder, List<Long> orderIds) {
        PayMethodEnum receiveType;
//        if (payOrder.getPayType().equals(PayMethodEnum.FAST_PAY) || payOrder.getPayType().equals(PayMethodEnum.SAND_BALANCE_PAY)) {
//            receiveType = PayMethodEnum.SAND_BALANCE_PAY;
//        } else
        if (payOrder.getChannel().equals(PayChannelEnum.LL_PAY)) {
            receiveType = PayMethodEnum.LL_BALANCE_PAY;
        } else {
            receiveType = PayMethodEnum.WALLET_PAY;
        }
//        log.info("支付单对象：{},receiveType：{}", JSONUtil.toJsonStr(payOrder), receiveType);
        List<SecondEquityPropsOrder> orders = equityPropsOrderDao.findWaitingPayByIds(orderIds);
        Assert.notEmpty(orders, () -> new GlobalRunTimeException("订单不存在"));
        Assert.isTrue(orders.size() == orderIds.size(), () -> new GlobalRunTimeException("订单数量不一致，请重新支付"));
        Date payTime = payOrder.getPayTime();
        BigDecimal lastPrice = null;
        List<Long> userEquityPropsIds = Lists.newArrayList();
        for (SecondEquityPropsOrder order : orders) {
            if (order.getWantSellOrderId() != null) {
                userEquityPropsService.updateWantSellToSales(order.getEquityPropsId(), order.getUserEquityPropsId(), order.getId(), order.getSalesUserId(), order.getBuyUserId(), payTime);
                ScrollWantSell wantSell = wantSellDao.getById(order.getWantSellOrderId());
                wantSellDao.paySuccess(wantSell.getId(), 1, order.getBuyPrice(), order.getCharge());
                scrollShopDao.addDealCount(wantSell.getShopId(), 1);
                if (wantSell.getWantSellCount() - wantSell.getSalesCount() == 1) {
                    wantSellDao.updateStatus(wantSell.getId(), WantSellOrderStatusEnum.FINISH);
                }
            } else {
                userEquityPropsService.updateToSales(order.getEquityPropsId(), order.getUserEquityPropsId(), order.getId(), order.getSalesUserId(), order.getBuyUserId(), payTime);
                Assert.isTrue(secondEquityPropsDao.updateLockStatusToSuccess(order.getSecondEquityPropsId(), payTime), () -> new GlobalRunTimeException("操作失败，请重试"));
            }
            order.setReceiveType(receiveType);
            Assert.isTrue(equityPropsOrderDao.updateStatusLockToSuccess(order.getId(), ObjectUtil.isNull(payTime) ? DateTime.now() : payTime, receiveType), () -> new GlobalRunTimeException("操作失败，请重试"));

            lastPrice = order.getBuyPrice();
            userEquityPropsIds.add(order.getUserEquityPropsId());
        }

        EquityProps equityProps = equityPropsDao.getById(orders.get(0).getEquityPropsId());
        userEquityPropsService.buyEquityPropsByUser(equityProps, orders.get(0).getBuyUserId(), UserEquityPropsGetTypeEnum.BUY, userEquityPropsService.getListByIds(userEquityPropsIds), "购买" + orders.get(0).getFirstTitle() + orders.size() + "个",
                payOrder.getId(), orders.get(0).getBuyPrice());
        equityPropsDao.updateNewDealPrice(equityProps.getId(), lastPrice);

        String lockKey = RedisKeyEnum.SECOND_USER_LOCK.getKey() + orders.get(0).getBuyUserId();
        redisTemplate.delete(lockKey);

        UserInfo user = userInfoDao.getById(orders.get(0).getBuyUserId());
        if (!user.getIsValid()) {
            userInfoDao.setIsValid(user.getId());
        }
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(orders.get(0).getBuyUserId(), SaasTaskTypeEnum.NEW_USERS_MAKE_THEIR_FIRST_PURCHASE, Convert.toBigDecimal(1), 0, equityProps.getId()), SaasTaskTypeEnum.NEW_USERS_MAKE_THEIR_FIRST_PURCHASE.name());
            }
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void extracted(SecondEquityPropsOrder order) {
        Assert.isTrue(equityPropsOrderDao.updateSettleFlag(order.getId()), () -> new GlobalRunTimeException("订单状态不正确"));
        StaticData scrollPropsId = staticDataDao.getByType("scroll_props_id");
        if (ObjectUtil.isNotNull("scroll_props_id") && Long.parseLong(scrollPropsId.getValue()) == order.getEquityPropsId().longValue()) {
            ScrollConfig config = scrollConfigDao.getConfig();
            equitySharePoolService.addPool(1L, order.getId(), order.getCharge().multiply(config.getPropsShareRatio()));
            equitySharePoolService.addPool(2L, order.getId(), order.getCharge().multiply(config.getPlatformShareRatio()));
            equitySharePoolService.addPool(3L, order.getId(), order.getCharge().multiply(config.getShareholderShareRatio()));
            equitySharePoolService.addPool(4L, order.getId(), order.getCharge().multiply(config.getStaffShareRatio()));
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    MetaMapSettleDTO metaMapSettleDTO = new MetaMapSettleDTO();
                    MetaMapSettleDTO order1 = metaMapSettleDTO.order(order.getOrderNo(), order.getBuyUserId(), MetaMapSettleSourceTypeEnum.SHOP, order.getBuyPrice(), order.getCharge(), order.getFirstTitle(), config.getId(), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    messageQueueHelper.sendMessage(MessageTopic.META_MAP_SETTLE, order1, MessageTopic.META_MAP_SETTLE, order.getOrderNo());
                }
            });
        } else {
            SecondEquityPropsConfig lastOneByEquityPropsId = equityPropsConfigDao.getLastOneByEquityPropsId(order.getEquityPropsId());
            if (ObjectUtil.isNotNull(lastOneByEquityPropsId) && lastOneByEquityPropsId.getPanelId() != null) {
                EquitySharePanel equitySharePanel = equitySharePanelDao.getById(lastOneByEquityPropsId.getPanelId());
                if (ObjectUtil.isNotNull(equitySharePanel)) {
                    equitySharePoolService.addPool(equitySharePanel, order.getId(), order.getCharge());
                }
            }
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    MetaMapSettleDTO metaMapSettleDTO = new MetaMapSettleDTO();
                    MetaMapSettleDTO order1 = metaMapSettleDTO.order(order.getOrderNo(), order.getBuyUserId(), MetaMapSettleSourceTypeEnum.PROP_ORDER, order.getBuyPrice(), order.getCharge(), order.getFirstTitle(), lastOneByEquityPropsId.getPanelId(), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    messageQueueHelper.sendMessage(MessageTopic.META_MAP_SETTLE, order1, MessageTopic.META_MAP_SETTLE, order.getOrderNo());
                }
            });
        }
        //TODO 二级权益道具只有卖家资金 6.3.6-pay 存在求购订单关联的二级权益道具订单
        PayOrder payOrder;
        //求购
        if (null != order.getWantBuyOrderId()) {
            ScrollWantBuy wantBuyOrder = scrollWantBuyDao.getById(order.getWantBuyOrderId());
            payOrder = payOrderDao.getByOrderNo(wantBuyOrder.getOrderNo());
        } else {
            payOrder = payOrderItemDao.getByOrderIdAndType(order.getId(),
                    SecondPayOrderItemTypeEnum.EQUITY_PROPS, PayTypeEnum.SECOND_EQUITY_PROPS);
        }
        if (payOrder.getChannel().equals(PayChannelEnum.LL_PAY)) {
            orderSettleService.create(order.getId(), order.getBuyPrice(), order.getOrderNo(), order.getSalesUserId(), payOrder,
                    WalletDetailTypeEnum.PROPS_SALES, order.getBuyPrice().subtract(order.getCharge()), SettleUserTypeEnum.USER,
                    ExpenditureRecordTypeEnum.SELL, BizTypeEnum.EQUITY_PROPS, MarketLevelEnum.SECOND);
            //TODO 订单剩余未分金额归平台 购买金额-用户分账金额=平台所得金额 此处只管卖家付款金额和直推 其他全是平台的 此处没有直推只有手续费
            //TODO 给平台增加待结算 有结余才算否则无意义
            if (order.getCharge().compareTo(BigDecimal.ZERO) > 0) {
                orderSettleService.create(order.getId(), order.getBuyPrice(), order.getOrderNo(), null, payOrder, WalletDetailTypeEnum.PLANT_LESS,
                        order.getCharge(), SettleUserTypeEnum.MERCHANT, ExpenditureRecordTypeEnum.PLANT_AMOUNT, BizTypeEnum.EQUITY_PROPS, MarketLevelEnum.SECOND);
            }
        } else {
            userWalletService.addIncomeRemit(order.getSalesUserId(), order.getOrderNo(), order.getBuyPrice(),
                    order.getCharge(), BigDecimal.ZERO, WalletDetailTypeEnum.PROPS_SALES, ExpenditureRecordTypeEnum.SELL);

        }


    }


    @Override
    public RealAmountVO valuation(UserInfo user, Long equityPropsId, List<Long> productIds) {

        List<SecondEquityProps> secondEquityPropsList = secondEquityPropsDao.getListByProductId(productIds);
        Assert.isTrue(productIds.size() == productIds.size(), "商品不存在或已被锁定");

        BigDecimal charge = BigDecimal.ZERO;
        BigDecimal realAmount = BigDecimal.ZERO;
        for (SecondEquityProps product : secondEquityPropsList) {
            charge = charge.add(product.getCharge());
            realAmount = realAmount.add(product.getSalesPrice());
        }

        EquityProps equityProps = equityPropsDao.getById(equityPropsId);
        RealAmountVO realAmountVO = new RealAmountVO();
        realAmountVO.setFirstTitle(equityProps.getFirstTitle());
        realAmountVO.setRealAmount(realAmount);
        realAmountVO.setCharge(charge);
        realAmountVO.setSumCharge(realAmount);
        realAmountVO.setEquityPropsId(secondEquityPropsList.get(0).getEquityPropsId());
        realAmountVO.setConsignCount(secondEquityPropsList.size());
        return realAmountVO;
    }

    @Override
    public RealAmountVO buyValuation(UserInfo user, Long equityPropsId, List<Long> orderIds) {
        List<SecondEquityPropsOrder> orders = equityPropsOrderDao.getListByIdsAndUserIdAndEquityPropsId(orderIds, user.getId(), equityPropsId);
        Assert.isTrue(orders.size() == orderIds.size(), "订单不存在或已支付");
        Assert.isFalse(orders.isEmpty(), () -> new GlobalRunTimeException("订单不存在"));
        BigDecimal charge = BigDecimal.ZERO;
        BigDecimal realAmount = BigDecimal.ZERO;
        for (SecondEquityPropsOrder order : orders) {
            charge = charge.add(order.getCharge());
            realAmount = realAmount.add(order.getBuyPrice());
        }
        EquityProps equityProps = equityPropsDao.getById(equityPropsId);
        RealAmountVO realAmountVO = new RealAmountVO();
        realAmountVO.setRealAmount(realAmount);
        realAmountVO.setFirstTitle(equityProps.getFirstTitle());
        realAmountVO.setCharge(charge);
        realAmountVO.setSumCharge(realAmount);
        realAmountVO.setEquityPropsId(orders.get(0).getEquityPropsId());
        realAmountVO.setConsignCount(orderIds.size());
        realAmountVO.setExpirationTimeStamp(orders.get(0).getCloseTime().getTime());
        realAmountVO.setNowTimeStamp(DateTime.now().getTime());
        return realAmountVO;
    }

    @Override
    public EquityPoPonsolidatedPaymentDetailsVO consolidatedPaymentDetails(UserInfo user) {
        EquityPoPonsolidatedPaymentDetailsVO vo = new EquityPoPonsolidatedPaymentDetailsVO();

        List<SecondEquityPropsOrder> lockOrder = secondEquityPropsOrderDao.getLockOrderByUserId(user.getId());
        Assert.isFalse(lockOrder.size() == 0, () -> new GlobalRunTimeException("不存在未支付订单"));
        Long equityPropsId = lockOrder.get(0).getEquityPropsId();
        EquityProps equityProps = equityPropsDao.getById(equityPropsId);
        Assert.notNull(equityProps, () -> new GlobalRunTimeException("未找到该商品"));

        StaticData scrollPropsId = staticDataDao.getByType("scroll_props_id");
        if (equityPropsId.longValue() != Long.parseLong(scrollPropsId.getValue())) {
            SecondEquityPropsConfig secondEquityPropsConfig = secondEquityPropsConfigDao.getLastOneByEquityPropsId(equityPropsId);
            Assert.notNull(secondEquityPropsConfig, () -> new GlobalRunTimeException("该道具已下架"));
        }

        vo.setFirstTitle(equityProps.getFirstTitle());
        vo.setCreationContent(equityProps.getCreationContent());
        vo.setEquityPropsId(equityProps.getId());

        BigDecimal sumBuyPrice = BigDecimal.ZERO;
        ArrayList<SecondEquityPropWaitPayOrderVO> orderList = Lists.newArrayList();
        for (SecondEquityPropsOrder order : lockOrder) {
            SecondEquityPropWaitPayOrderVO secondEquityPropWaitPayOrderVO = new SecondEquityPropWaitPayOrderVO();
            secondEquityPropWaitPayOrderVO.setBuyPrice(order.getBuyPrice());
            secondEquityPropWaitPayOrderVO.setOrderId(order.getId());
            secondEquityPropWaitPayOrderVO.setOrderNo(order.getOrderNo());
            sumBuyPrice = sumBuyPrice.add(order.getBuyPrice());
            orderList.add(secondEquityPropWaitPayOrderVO);
        }

        vo.setSumBuyPrice(sumBuyPrice);
        vo.setOrderLists(orderList);


        return vo;
    }

    @Override
    public EquityPropWaitPayOrderDetailsVO waitPayOrderDetails(UserInfo user, Long orderId) {
        SecondEquityPropsOrder order = equityPropsOrderDao.getOneByIdAndUserId(orderId, user.getId());
        Assert.notNull(order, () -> new GlobalRunTimeException("订单不存在"));
        Assert.isTrue(order.getStatus() == OrderStatusEnum.WAIT_PAY, () -> new GlobalRunTimeException("订单状态不正确"));

        EquityProps equityProps = equityPropsDao.getById(order.getEquityPropsId());
        Assert.notNull(equityProps, () -> new GlobalRunTimeException("未找到该商品"));
        StaticData equityPropsId = staticDataDao.getByType("scroll_props_id");
        if (order.getEquityPropsId().longValue() != Long.parseLong(equityPropsId.getValue())) {
            SecondEquityPropsConfig secondEquityPropsConfig = secondEquityPropsConfigDao.getLastOneByEquityPropsId(order.getEquityPropsId());
            Assert.notNull(secondEquityPropsConfig, () -> new GlobalRunTimeException("该道具已下架"));
        }
        EquityPropWaitPayOrderDetailsVO vo = new EquityPropWaitPayOrderDetailsVO();
        vo.setBuyPrice(order.getBuyPrice());
        vo.setOrderId(order.getId());
        vo.setEquityPropsId(order.getEquityPropsId());
        vo.setExpirationTimeStamp(order.getCloseTime().getTime());
        vo.setNowTimeStamp(DateTime.now().getTime());
        vo.setFirstTitle(equityProps.getFirstTitle());
        vo.setCreationContent(equityProps.getCreationContent());
        vo.setStatus(order.getStatus());
        vo.setOrderNo(order.getOrderNo());
        vo.setBuyUserNickName(user.getNickName());
        UserInfo salesUser = userInfoDao.getById(order.getSalesUserId());

        vo.setSalesUserNickName(salesUser.getNickName());
        vo.setCreateTime(order.getCreateTime());


        return vo;
    }

    @Override
    public SecondEquityPropTradingTendDetailsVO tradingTendDetails(Long equityPropsId) {
        SecondEquityPropsConfig config = configDao.getLastOneByEquityPropsId(equityPropsId);
        Assert.notNull(config, () -> new GlobalRunTimeException("权益道具未上架"));
        Assert.isTrue(config.getStatus(), () -> new GlobalRunTimeException("权益道具未上架"));
        return equityPropsOrderDao.tradingTendDetails(equityPropsId);
    }

    @Override
    public Page<SecondEquityPropTradingTendPageVO> flowRecord(Long equityPropsId, Page page) {
        return equityPropsOrderDao.flowRecord(page, equityPropsId);
    }

    @Override
    public Page<SecondEquityPropBuyOrderPageVO> orderPage(Page page, UserInfo user, OrderStatusEnum status, Date searchTime) {
        DateTime beginTime = null;
        DateTime endTime = null;

        if (ObjectUtil.isNotNull(searchTime)) {
            beginTime = DateUtil.beginOfMonth(searchTime);
            endTime = DateUtil.endOfMonth(searchTime);
        }
        return equityPropsOrderDao.orderPage(page, user.getId(), status, beginTime, endTime);
    }

    @Override
    public SecondEquityPropBuyOrderPageVO buyOrderDetail(UserInfo user, Long id) {
        SecondEquityPropBuyOrderPageVO orderPageVO = equityPropsOrderDao.buyOrderDetail(user.getId(), id);
        PayOrder payOrder;
        //求购
        if (null != orderPageVO.getWantBuyOrderId()) {
            ScrollWantBuy wantBuyOrder = scrollWantBuyDao.getById(orderPageVO.getWantBuyOrderId());
            payOrder = payOrderDao.getByOrderNo(wantBuyOrder.getOrderNo());
        } else {
            payOrder = payOrderItemDao.getByOrderIdAndType(orderPageVO.getOrderId(),
                    SecondPayOrderItemTypeEnum.EQUITY_PROPS, PayTypeEnum.SECOND_EQUITY_PROPS);
        }
        if (ObjectUtil.isNotNull(payOrder)) {
            orderPageVO.setPayIcon(null != payOrder.getPayType() ? payOrder.getPayType().getIcon() : null);
            orderPageVO.setPayType(payOrder.getPayType());
        }
        return orderPageVO;
    }

    @Override
    public SecondEquityPropBuyOrderPageVO salesOrderDetail(UserInfo user, Long id) {
        return equityPropsOrderDao.salesOrderDetail(user.getId(), id);
    }

    @Override
    public Page<SecondEquityPropBuyOrderPageVO> salesOrderPage(Page page, UserInfo user, Date searchTime) {
        DateTime beginTime = null;
        DateTime endTime = null;

        if (ObjectUtil.isNotNull(searchTime)) {
            beginTime = DateUtil.beginOfMonth(searchTime);
            endTime = DateUtil.endOfMonth(searchTime);
        }
        return equityPropsOrderDao.salesOrderPage(page, user.getId(), beginTime, endTime);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchCancelOrder(Long equityPropsId, List<Long> orderIds, UserInfo user) {
        List<SecondEquityPropsOrder> orderList = equityPropsOrderDao.getListByIdsAndUserIdAndEquityPropsId(orderIds, user.getId(), equityPropsId);
        Assert.isTrue(orderList.size() == orderIds.size(), "订单不存在或已支付");
        for (SecondEquityPropsOrder order : orderList) {
            cancelOrder(order);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrder(SecondEquityPropsOrder order) {

        String key = StrUtil.format(RedisKeyEnum.LOCK_CONSIGN_EQUITY_PROPS.getKey(), order.getId());
        RLock orderLock = redisson.getLock(key);
        boolean heldByCurrentThread = orderLock.tryLock();
        if (!heldByCurrentThread) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        try {
            Assert.isTrue(equityPropsOrderDao.updateStatusLockToCancel(order.getId(), OrderStatusEnum.OVERDUE), () -> new GlobalRunTimeException("订单状态不正确"));
            if (order.getWantSellOrderId() != null) {
                ScrollWantSell wantSell = wantSellDao.getById(order.getWantSellOrderId());
                wantSellDao.subFreeze(wantSell.getId(), 1);
                Assert.isTrue(userEquityPropsDao.updateConsignToOnConsign(order.getUserEquityPropsId()), () -> new GlobalRunTimeException("更新寄售状态失败"));
            } else {
                Assert.isTrue(secondEquityPropsDao.updateStatusToCancel(order.getSecondEquityPropsId()), () -> new GlobalRunTimeException("操作失败，请重试"));
            }

        } catch (Exception e) {
            log.error("取消订单失败", e);
        } finally {
            orderLock.unlock();
        }
    }

    @Override
    public List<SecondEquityPropsOrder> getPreTimeOutOrderIds(DateTime offset) {
        return equityPropsOrderDao.getPreTimeOutOrderIds(offset);
    }

    @Override
    public Integer countOrder(Long userId) {
        LambdaQueryWrapper<SecondEquityPropsOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SecondEquityPropsOrder::getBuyUserId, userId);
        queryWrapper.eq(SecondEquityPropsOrder::getStatus, OrderStatusEnum.PAYMENT);
        queryWrapper.last(" limit 5");
        return secondEquityPropsOrderDao.list(queryWrapper).size();
    }

    @Override
    public BigDecimal getLastPrice(Long equityPropsId) {
        return equityPropsOrderDao.getLastPrice(equityPropsId);
    }

    @Override
    public IPage<SecondEquityPropsOrder> wantBuyOrderPage(Page page, Long wantBuyOrderId) {
        return equityPropsOrderDao.wantBuyOrderPage(page, wantBuyOrderId);
    }

    @Override
    public IPage<SecondEquityPropsOrder> wantBuyOrderPage(Page page, Long wantBuyOrderId, Long salesUserId, Date startCreateTime, Date endCreateTime, Date startPayTime, Date endPayTime) {
        return equityPropsOrderDao.wantBuyOrderPage(page, wantBuyOrderId, salesUserId, startCreateTime, endCreateTime, startPayTime, endPayTime);
    }

}